﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data;
using System.Runtime.CompilerServices;
using VAdvantage.Classes;
using VAdvantage.Logging;
using System.Data.SqlClient;


namespace VAdvantage.DataBase
{
    public class Trx
    {
        /** Logger					*/
        private VLogger log = null;
        /**	Transaction Cache					*/
        private static CCache<String, Trx> _cache = null;	//	create change listener
        private String _trxName = null;
        private bool _active = false;


        public Trx(string trxName)
            : this(trxName, null)
        {
            if (log == null)
                log = VLogger.GetVLogger(this.GetType().FullName);
        }

        private Trx(string trxName, object o)
        {
            this._trxName = trxName;

        }

        internal DataSet ExecuteDataset(string sql, SqlParameter[] param, string trxName)
        {
            return null;
        }

        public bool Commit()
        {
            bool isCommiting = true;
            try
            {
                var client = Utility.AEnv.GetDataServiceDBClient();

                client.CommitCompleted += (s, e) =>
                {
                    isCommiting = false;
                };
                client.CommitAsync(_trxName);
                client.CloseAsync();

                while (isCommiting)
                {
                    System.Threading.Thread.Sleep(5);
                }
            }
            catch (Exception sqlex)
            {
                //ShowMessage.Error("Error: " + sqlex.Message, false, "");
                log.Log(Level.SEVERE, _trxName, sqlex);
                //maintain log if any
            }

            _active = false;
            return false;
        }

        public bool Rollback()
        {
            bool isRollingBack = true;
            try
            {
                var client = Utility.AEnv.GetDataServiceDBClient();

                client.RollbackCompleted += (s, e) =>
                {
                    isRollingBack = false;
                };
                client.RollbackAsync(_trxName);
                client.CloseAsync();

                while (isRollingBack)
                {
                    System.Threading.Thread.Sleep(5);
                }
            }
            catch (Exception sqlex)
            {
                //maintain log if any
            }

            _active = false;
            return false;
        }


        /// </summary>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void Close()
        {
            if (_cache != null)
                _cache.Remove(GetTrxName());

            bool isClosing = true;
            try
            {
                var client = Utility.AEnv.GetDataServiceDBClient();

                client.CloseTrxCompleted += (s, e) =>
                {
                    isClosing = false;
                };
                client.CloseTrxAsync(_trxName);
                client.CloseAsync();

                while (isClosing)
                {
                    System.Threading.Thread.Sleep(5);
                }

            }
            catch (Exception sqlex)
            {
                log.Log(Level.SEVERE, _trxName, sqlex);
                //////ShowMessage.Error("Connection Error : " + sqlex.Message, false, _trxName);
            }

            // _conn = null;
            _active = false;
            log.Config(_trxName);
            log.Config(_trxName);
        }



        public string GetTrxName()
        {
            return this._trxName;
        }

        /// <summary>
        /// Get Transaction
        /// </summary>
        /// <param name="trxName">trx name</param>
        /// <param name="createNew">if false, null is returned if not found</param>
        /// <returns>Transaction or null</returns>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static Trx Get(String trxName, bool createNew)
        {
            if (trxName == null || trxName.Length == 0)
                throw new ArgumentException("No Transaction Name");

            if (_cache == null)
            {
                _cache = new CCache<String, Trx>("Trx", 10, -1);	//	no expiration
            }

            Trx retValue = (Trx)_cache[trxName];
            if (retValue == null && createNew)
            {
                retValue = new Trx(trxName);
                _cache.Add(trxName, retValue);

            }
            return retValue;
        }


        public static string CreateTrxName(string prefix)
        {
            if (prefix == null || prefix.Length == 0)
                prefix = "Trx";
            prefix += "_" + CommonFunctions.CurrentTimeMillis();
            return prefix;
        }
    }
}
